# -*- coding: utf-8 -*-
""" A Progress Dialog module

    :Author:
      - 20111202-20120110 Roberto Vidmar

    :Revision:  $Revision: 52 $
                $Date: 2012-11-12 09:07:15 +0000 (Mon, 12 Nov 2012) $

    :Copyright: 2011-2012
                Nicola Creati <ncreati@inogs.it>
                Roberto Vidmar <rvidmar@inogs.it>

    :License: MIT/X11 License (see :download:`license.txt
                               <../../license.txt>`)
"""

import sys
#import time
from qtCompat import QtCore, QtGui, Signal

#===============================================================================
class ProgressDialog(QtGui.QDialog):
  """ Processing gui with progress bar and message
  """

  # Custom signal that notifies abort of the process
  abortSignal = Signal(object)

  def __init__(self, tf, parent=None, title='Processor Progress Dialog',
    msg='The Message.', value=0):
    """ Create a new ProgressDialog instance.

      :param tf: a :class:`ThreadedFunc` instance
      :type tf: :class:`ThreadedFunc`
      :param parent: parent widget
      :type parent: QtGui widget
      :param title: title for the progress dialog
      :type title: string, unicode
      :param msg: progress message
      :type msg: string, unicode
      :param value: initial value
      :type value: int
      :raises:
    """

    super(ProgressDialog, self).__init__(parent)

    self.setWindowTitle(title)

    # Set the minimu width
    #self.setMinimumWidth(320)

    # Main layout
    l = QtGui.QVBoxLayout(self)

    # Standard progress bar
    self._msg = QtGui.QLabel(msg)
    self._bar = QtGui.QProgressBar()
    self._bar.setValue(value)

    # Dialog button with cancel to stop the thread
    self._buttonBox = QtGui.QDialogButtonBox(self)
    self._buttonBox.setObjectName("buttonBox")
    self._buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Abort)

    # Final layout
    l.addWidget(self._msg)
    l.addWidget(self._bar)
    l.addWidget(self._buttonBox)

    self._buttonBox.clicked.connect(tf.abort)
    tf.progressSignal.connect(self.progress)
    tf.closeSignal.connect(self.onClose)

    # Show the widget
    self.setMinimumSize(QtCore.QSize(300, 100))
    self.exec_()

  def showMessage(self, flag=True):
    """ Show/Hide message

      :param flag: Show/Hide message
      :type flag: bool
      :raises:
    """
    self._msg.setVisible(flag)

  def progress(self, value):
    """ Update progress bar

      :param value: progress value
      :type value: int [0, 100]
      :raises:
    """
    self._bar.setValue(value)

  def setMessage(self, msg):
    """ Set text message

      :param msg: text message
      :type msg: string, unicode
      :raises:
    """
    self._msg.setText(msg)

  def onClose(self):
    self.close()

#===============================================================================
class ThreadedFunc(QtCore.QThread):
  """ A class to run a function inside a Thread.
  """
  progressSignal = Signal(object)
  endedSignal = Signal(object)
  closeSignal = Signal()

  def __init__(self, func, *args, **kargs):
    """ Create a new ThreadedFunc instance.

        \*args and \**kargs are fed to `func`

      :param func: the function to run
      :type func: function
      :param \*args: various
      :type \*args: various
      :param \*kargs: various
      :type \*kargs: various
      :raises:
    """
    super(ThreadedFunc, self).__init__()
    self._func = func
    self._quit = False
    self._args = args
    self._kargs = kargs
    self.start()

  def abort(self):
    """ Set the "we want abort" flag
    """
    self._quit = True

  def quit(self):
    """ A method to check if the "we want abort" flag is set from inside
        the threaded function.
    """
    return True if self._quit else False

  def run(self):
    """ Start the Thread
    """
    returnValue = self._func(self.progressSignal.emit, self.quit,
      *self._args, **self._kargs)
    self.endedSignal.emit(returnValue)
    self.closeSignal.emit()

#===============================================================================
if __name__ == "__main__":

  import signal
  import time
  signal.signal(signal.SIGINT, signal.SIG_DFL)

  def f(progress, qfunc, *args, **kargs):
    for i in range(51):
      if qfunc():
        return None
      v = 2 * i
      print "arg=", args, v
      progress(v)
      time.sleep(0.1)
    return "Something"

  app = QtGui.QApplication(sys.argv)
  tf = ThreadedFunc(f, 'pippo', 'pluto')
  pd = ProgressDialog(tf)
  print "Progress dialog ended, execution can continue....."
  app.exec_()
